﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AAA.Meta.Quote.Data;
using AAA.Base.Util;
using AAA.Base.Util.SafeCollection;

namespace AAA.Quote
{
    public class KBarManager
    {
        private int _iCurrentTimeIndex = 0;
        private bool _needUpdateKBarTime = true;
        private bool _needSearchBarIndex = false;

        private string _strSessionStartTime = "08:45:00";

        public string SessionStartTime
        {
            get { return _strSessionStartTime; }
            set 
            { 
                _strSessionStartTime = value; 
                UpdateKBarTime();
            }
        }

        private string _strSessionEndTime = "13:45:00";

        public string SessionEndTime
        {
            get { return _strSessionEndTime; }
            set 
            { 
                _strSessionEndTime = value; 
                UpdateKBarTime();
            }
        }

        private DateTime _dtToday;

        public DateTime Today
        {
            get { return _dtToday; }
            set 
            { 
                _dtToday = value;
                UpdateKBarTime();
            }
        }

        private BarCompression _barCompression;

        public BarCompression BarCompression
        {
            get { return _barCompression; }
            set 
            { 
                _barCompression = value;
                UpdateKBarTime();
            }
        }

        private List<DateTime> _lstBarTime = new List<DateTime>();

        private ThreadSafeList<BarRecord> _lstBarRecord;

        public ThreadSafeList<BarRecord> BarRecordList
        {
            get { return _lstBarRecord; }
            set { _lstBarRecord = value; }
        }

        public KBarManager(string strSessionStartTime, string strSessionEndTime, DateTime dtToday, BarCompression barCompression)
        {
            _needUpdateKBarTime = false;
            SessionStartTime = strSessionStartTime;
            SessionEndTime = strSessionEndTime;
            Today = dtToday;
            BarCompression = barCompression;
            _needUpdateKBarTime = true;
            UpdateKBarTime();
        }

        private void UpdateKBarTime()
        {
            if (_needUpdateKBarTime == false)
                return;

            _lstBarTime = KBarHelper.GenerateBarTime(SessionStartTime, SessionEndTime, Today, BarCompression);

            _iCurrentTimeIndex = 0;
            _needSearchBarIndex = true;

        }

        private void SearchBarIndex(DateTime dtCurrentTime)
        {
            while (_lstBarTime[_iCurrentTimeIndex].CompareTo(dtCurrentTime) < 0)
            {
                _iCurrentTimeIndex++;
                if (_iCurrentTimeIndex == _lstBarTime.Count)
                    return;
            }
        }

        // return true if change KBar
        public bool UpdateTick(TickData tickData)
        {           
            bool isChangeKBar = false;
            BarRecord barRecord;
            DateTime dtTickTime = DateTimeHelper.Parse(tickData.Date + " " + tickData.Time);

            if (_needSearchBarIndex)
            {
                SearchBarIndex(dtTickTime);
                _needSearchBarIndex = false;
            }

            if (_iCurrentTimeIndex >= _lstBarTime.Count)
                return isChangeKBar;

            //若不是開盤第一根, 則需檢查是否為前一根K的tick, 若是則丟棄
            if (_iCurrentTimeIndex > 0)
            {
                if (dtTickTime.CompareTo(_lstBarTime[_iCurrentTimeIndex - 1]) <= 0)
                    return isChangeKBar;
            }
                        
            //組合K棒
            if ((dtTickTime.CompareTo(_lstBarTime[_iCurrentTimeIndex]) >= 0) || (dtTickTime.ToString("HH:mm:ss") == _strSessionStartTime))
            {
                isChangeKBar = true;                
                barRecord = new BarRecord();

                try
                {
                    barRecord.BarCompression = BarRecordList[BarRecordList.Count - 1].BarCompression;
                }
                catch{}

                barRecord.BarDateTime = _lstBarTime[(_iCurrentTimeIndex + 1 == _lstBarTime.Count ? _iCurrentTimeIndex : _iCurrentTimeIndex + 1)];
                //barRecord.BarDateTime = _lstBarTime[_iCurrentTimeIndex];
                barRecord[BarRecord.OPEN] = tickData.Price;
                barRecord[BarRecord.HIGH] = tickData.Price;
                barRecord[BarRecord.LOW] = tickData.Price;
                barRecord[BarRecord.CLOSE] = tickData.Price;
                barRecord[BarRecord.VOLUME] = tickData.Volume;

                _iCurrentTimeIndex++;
                BarRecordList.Add(barRecord);
            }
            else
            {
                barRecord = _lstBarRecord[_lstBarRecord.Count - 1];

                barRecord[BarRecord.CLOSE] = tickData.Price;
                barRecord[BarRecord.HIGH] = Math.Max(barRecord[BarRecord.HIGH], tickData.Price);
                barRecord[BarRecord.LOW] = Math.Min(barRecord[BarRecord.LOW], tickData.Price);
                barRecord[BarRecord.VOLUME] += tickData.Volume;
            }

            return isChangeKBar;
        }

    }
}
